using System;
using System.Collections.Generic;
using System.Linq;
using SubversionReports.Entities;
using SubversionReports.Utilities;
using System.Web.UI.WebControls;

namespace SubversionReports.Web.Controls
{
    public partial class ChangeLog : PagedControl
    {
        private Repository repository;

        /// <summary>
        /// Gets the repository.
        /// </summary>
        /// <value>The repository.</value>
        protected Repository Repository
        {
            get
            {
                if (repository == null)
                    repository = SvnWebDav.GetRepositoryLog(SvnWebDav.CurrentRepositoryRootUrl, SvnWebDav.CurrentRepositoryUsername, SvnWebDav.CurrentRepositoryPassword);
                return repository;
            }
        }

        /// <summary>
        /// Gets the change log path.
        /// </summary>
        /// <value>The change log path.</value>
        protected string ChangeLogPath
        {
            get
            {
                if (Request["ChangeLog"] != null && Repository.TaggedPaths.ContainsKey(Request["ChangeLog"]))
                    return Request["ChangeLog"];
                return Repository.TaggedPaths.Any() ? Repository.TaggedPaths.First().Key : null;
            }
        }

        /// <summary>
        /// Gets from revision id.
        /// </summary>
        /// <value>From revision id.</value>
        protected int FromRevisionId
        {
            get
            {
                int from;
                return (!int.TryParse(Request["From"], out from))
                    ? Repository.TaggedPaths[ChangeLogPath][Repository.TaggedPaths[ChangeLogPath].Count - 1].EndRevision
                    : from;
            }
        }

        /// <summary>
        /// Gets to revision id.
        /// </summary>
        /// <value>To revision id.</value>
        protected int ToRevisionId
        {
            get
            {
                int to;
                return (!int.TryParse(Request["To"], out to))
                    ? Repository.TaggedPaths[ChangeLogPath][Repository.TaggedPaths[ChangeLogPath].Count - 1].StartRevision
                    : to;
            }
        }

        /// <summary>
        /// Handles the Load event of the Page control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (SvnWebDav.AuthenticationSuceeded && Visible)
            {
                BindDropDownLists();
                BindRevisionRepeaters();
            }
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the TagPathDropDownList control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void TagPathDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            DropDownList tagPathDropDownList = sender as DropDownList;
            if (tagPathDropDownList != null)
                Response.Redirect(string.Format("{0}?ChangeLog={1}", Request.FilePath, tagPathDropDownList.SelectedValue), true);
        }

        /// <summary>
        /// Handles the Click event of the GoButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void GoButton_Click(object sender, EventArgs e)
        {
            int from;
            if (!int.TryParse(EndRevisionDropDownList.SelectedValue, out from))
                from = FromRevisionId;
            int to;
            if (!int.TryParse(StartRevisionDropDownList.SelectedValue, out to))
                to = ToRevisionId;
            Response.Redirect(string.Format("{0}?ChangeLog={1}&From={2}&To={3}", Request.FilePath, Request["ChangeLog"], from, to), true);
        }

        /// <summary>
        /// Binds the drop down lists.
        /// </summary>
        private void BindDropDownLists()
        {
            Repository.TaggedPaths.ForEach(delegate(KeyValuePair<string, List<Tag>> tp)
            {
                ListItem tagListItem = new ListItem(tp.Key);
                tagListItem.Selected = tp.Key.Equals(ChangeLogPath);
                TagPathDropDownList.Items.Add(tagListItem);
            });
            List<ListItem> endRevisionListItems = new List<ListItem>();
            List<ListItem> startRevisionListItems = new List<ListItem>();
            Repository.TaggedPaths[ChangeLogPath].ForEach(delegate(Tag tag)
            {
                string label = string.Format("{0} ({1}-{2})", tag.Name, tag.StartRevision, tag.EndRevision);
                ListItem fromItem = new ListItem(label, tag.EndRevision.ToString());
                fromItem.Selected = FromRevisionId.Equals(tag.EndRevision);
                endRevisionListItems.Add(fromItem);

                ListItem toItem = new ListItem(label, tag.StartRevision.ToString());
                toItem.Selected = ToRevisionId.Equals(tag.StartRevision);
                startRevisionListItems.Add(toItem);
            });
            endRevisionListItems.Reverse();
            endRevisionListItems.ForEach(delegate(ListItem li) { EndRevisionDropDownList.Items.Add(li); });
            startRevisionListItems.Reverse();
            startRevisionListItems.ForEach(delegate(ListItem li) { StartRevisionDropDownList.Items.Add(li); });
        }

        /// <summary>
        /// Binds the revision repeater.
        /// </summary>
        private void BindRevisionRepeaters()
        {
            HeaderLabel.Text = string.Format("Change Log for {0}", ChangeLogPath);
            RangeLabel.Text = string.Format("Between revision {0} and {1}.", FromRevisionId, ToRevisionId);

            List<Tag> tagsToDisplay = new List<Tag>();

            Repository.TaggedPaths[ChangeLogPath].ForEach(delegate(Tag t)
                                     {
                                         if(t.EndRevision <= FromRevisionId && t.StartRevision >= ToRevisionId)
                                             tagsToDisplay.Add(t);
                                     });
            tagsToDisplay.Reverse();
            TagRepeater.DataSource = tagsToDisplay;
            TagRepeater.DataBind();
        }
    }
}